home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / System / XFD / Developer / Sources / ASM / SZDD.a < prev    next >
Encoding:
Text File  |  2001-09-16  |  5.1 KB  |  189 lines

  1. ; XFD external slave for SZDD files (C) 2000 Stuart Caie <kyzer@4u.net>
  2. ; $VER: SZDD.asm 1.3 (29.06.2000)
  3. ; v1.1: better xfd name, eliminated 4k buffer
  4. ; v1.2: better header text, no code changed
  5. ; v1.3: off-by-one error fixed, spaces-vs-nulls error fixed
  6. ; v1.4: added LPAK format. This is the same algo as the M$ format, but with
  7. ;       less headers and a different window start offset.
  8. ;
  9. ; Files in the SZDD file format are created with Microsoft's COMPRESS.EXE
  10. ; program, and decompressed with Microsoft's EXPAND.EXE program. The file,
  11. ; when compressed, usually has an underscore as the last character in its
  12. ; filename, ie HELLO.EX_ or VBRUN666.DL_
  13. ;
  14. ; File header format:
  15. ; 4 bytes : "SZDD" (0x53,0x5A,0x44,0x44) - magic ID
  16. ; 4 bytes : 0x88,0xF0,0x27,0x33 - more magic ID
  17. ; 1 byte  : compression mode - only 'A' (0x41) known
  18. ; 1 byte  : the character missing from the end of the filename (0=unknown)
  19. ; 4 bytes : A,B,C,D. unpacked size of file is (D<<24)|(C<<16)|(B<<8)|(A)
  20. ; n bytes : the compressed data
  21. ;
  22. ; The compressed data format is basically LZSS
  23. ; - one control byte, whose bits dictate the format of the next 8 elements,
  24. ;   in the order of LSB to MSB:
  25. ;   - if a bit is set, the next element is a single byte literal
  26. ;   - otherwise, the next element is a repeat: two bytes, %AAAAAAAA %BBBBCCCC
  27. ;     where offset = %BBBBAAAAAAAA and length is %CCCC + 3
  28. ; - this repeats until enough data has been unpacked
  29. ;
  30. ; A 4096 byte wraparound buffer must be kept by the decruncher. A wraparound
  31. ; pointer starts at 4096-16 and each outputted byte must be written at that
  32. ; position and the pointer advanced by one. The offsets of the compressed
  33. ; data refer to an absolute position in this buffer, which may be before the
  34. ; current pointer, or after it. The buffer's initial state is that all
  35. ; elements are the space character (0x20).
  36. ;
  37. ; Also, it seems that there can often be superfluous data at the end of a
  38. ; file - I can only go by the uncompressed size, so I can only really test
  39. ; running out of source data. Some files end in the middle of a run, so I
  40. ; can't test if they exactly reach the endpoint and no more.
  41. ;
  42. ; This code was based on code found in a document describing the Windows Help
  43. ; file format, written by M. Winterhoff <100326.2776@compuserve.com>.
  44. ;
  45.  
  46. SZDD_WNDSIZE=4096
  47. SZDD_WNDMASK=4095
  48. SZDD_HDRLEN=14
  49. LPAK_HDRLEN=8
  50. SZDD_OVERRUN=144
  51.  
  52.     include    exec/memory.i
  53.     include    libraries/xfdmaster.i
  54.     include    lvo/exec_lib.i
  55.  
  56.     IFD    TEST
  57.     include    xfdExeHead.a
  58.     ENDC
  59.  
  60. ForeMan    dc.l    $70FF4E75,XFDF_ID    ; id
  61.     dc.w    XFDF_VERSION        ; foreman version
  62.     dcb.w    5,0            ; reserved stuff
  63.     dc.l    SZDDslv            ; first slave
  64. SZDDslv    dc.l    LPAKslv
  65.     dc.w    XFDS_VERSION,39
  66.     dc.l    SZDDnam
  67.     dc.w    XFDPFF_DATA!XFDPFF_RECOGLEN!XFDPFF_USERTARGET,0
  68.     dc.l    SZDD_recog,SZDD_decrunch,0,0
  69.     dc.l    0,SZDD_HDRLEN
  70. LPAKslv    dc.l    0
  71.     dc.w    XFDS_VERSION,39
  72.     dc.l    LPAKnam
  73.     dc.w    XFDPFF_DATA!XFDPFF_RECOGLEN!XFDPFF_USERTARGET,0
  74.     dc.l    LPAK_recog,SZDD_decrunch,0,0
  75.     dc.l    0,LPAK_HDRLEN
  76.  
  77. LPAK_recog
  78.     cmp.l    #"LPAK",(a0)+
  79.     bne.s    _rfail
  80.     move.l    (a0)+,d0
  81.     bra.s    _recog
  82.  
  83. SZDD_recog
  84.     cmp.l    #"SZDD",(a0)
  85.     bne.s    _rfail
  86.     move.l    10(a0),d0
  87.     rol.w    #8,d0
  88.     swap    d0
  89.     rol.w    #8,d0
  90. _recog    move.l    d0,xfdrr_FinalTargetLen(a1)
  91.     add.l    #SZDD_OVERRUN,d0
  92.     move.l    d0,xfdrr_MinTargetLen(a1)
  93.     moveq    #1,d0            ; return success
  94.     rts
  95. _rfail    moveq    #0,d0
  96.     rts
  97.  
  98. SZDD_decrunch
  99.     movem.l    d2-d7/a2-a6,-(sp)
  100.     move.l    a0,a4                ; a4 = BufferInfo
  101.  
  102.     move.l    xfdbi_SourceBuffer(a4),a0    ; a0 = src
  103.     move.l    a0,a2
  104.     adda.l    xfdbi_SourceBufLen(a4),a2    ; a2 = ends
  105.  
  106.     ; skip header and set up some stuff 
  107.     cmp.l    #"SZDD",(a0)
  108.     beq.s    .szdd
  109.     addq.l    #LPAK_HDRLEN,a0
  110.     move.w    #SZDD_WNDSIZE-18,d7        ; d7 = posn
  111.     bra.s    .cont
  112. .szdd    adda.w    #SZDD_HDRLEN,a0
  113.     move.w    #SZDD_WNDSIZE-16,d7        ; d7 = posn
  114. .cont
  115.  
  116.     move.l    xfdbi_UserTargetBuf(a4),a1    ; a1 = dest
  117.     move.l    a1,a3
  118.     adda.l    xfdbi_TargetBufSaveLen(a4),a3    ; a3 = endd
  119.     move.l    a1,d3                ; d3 = start
  120.  
  121.     move.w    #SZDD_WNDMASK,d6        ; d6 = bufmask
  122.  
  123. .mainlp    move.b    (a0)+,d5            ; d5 = bits
  124.     moveq    #0,d4                ; d4 = mask
  125. .bitlp    btst.b    d4,d5
  126.     beq.s    .rep
  127.  
  128.     ; literal
  129.     move.b    (a0)+,(a1)+
  130.     addq.w    #1,d7
  131.     bra.s    .nxtbit
  132.  
  133. .rep    ; repeat
  134.     moveq    #0,d0
  135.     move.b    (a0)+,d0    ; d0 = offset
  136.     move.b    (a0)+,d1    ; d1 = length
  137.  
  138.     moveq    #0,d2
  139.     move.b    d1,d2
  140.     asl.w    #4,d2
  141.     move.b    #0,d2
  142.     or.w    d2,d0
  143.  
  144.     andi.w    #$f,d1
  145.     addq.b    #3,d1
  146.  
  147.     and.w    d6,d7
  148.     cmp.w    d0,d7
  149.     bhi.s    .noadd        ; if (offset <= posn) don't add WNDSIZE
  150.     add.w    #SZDD_WNDSIZE,d7; [or bset #12,d7 - but that's no shorter]
  151. .noadd    lea    (a1,d0.w),a5    ; a5 = rep, = dest+offset-posn
  152.     suba.w    d7,a5
  153.     add.w    d1,d7        ; posn += length
  154.  
  155. .clr    cmp.l    a5,d3        ; if rep >= base, stop doing clearing
  156.     bls.s    .noclr
  157.     move.b    #' ',(a1)+    ; clear one byte
  158.     addq.l    #1,a5
  159.     subq.w    #1,d1        ; length--
  160.     beq.s    .nxtbit
  161.     bra.s    .clr
  162.  
  163. .noclr    move.b    (a5)+,(a1)+    ; *dest++=*rep++
  164.     subq.w    #1,d1        ; while (length--)
  165.     bne.s    .noclr
  166.  
  167. .nxtbit    cmp.l    a1,a3        ; if dest >= endd, stop now
  168.     bcs.s    .done
  169.  
  170.     addq.l    #1,d4        ; next bit, from 0-7
  171.     cmp.b    #8,d4
  172.     bcs.s    .bitlp        ; if d4<8, goto .bitlp
  173.  
  174.     cmp.l    a0,a2
  175.     bcc.s    .mainlp        ; if src < ends, go back to main loop
  176.  
  177. .corupt    move.w    #XFDERR_CORRUPTEDDATA,xfdbi_Error(a4)
  178.     moveq    #0,d0
  179.      bra.s    .exit
  180. .done    clr.w    xfdbi_Error(a4)
  181.     moveq    #1,d0
  182. .exit    movem.l    (sp)+,d2-d7/a2-a6
  183.     rts
  184.  
  185.  
  186. SZDDnam    dc.b    '(SZDD) Microsoft Data Cruncher',0
  187. LPAKnam    dc.b    '(LPAK) Data Cruncher',0
  188.     dc.b    '$VER: SZDD 1.4 (16.09.2000) by <kyzer@4u.net>',0
  189.